#include "MarsPrecompile.h"
#include "MarsCLPlatform.h"
#include "MarsCLDevice.h"

using namespace GP;

CLPlatform::CLPlatform( PlatformVendor ePlatformVendor, cl_platform_id id )
	: Platform( ePlatformVendor )
	, m_platformId( id )
{
	InitDevice();
}

void CLPlatform::InitDevice()
{
	InitDeviceByType( CL_DEVICE_TYPE_CPU, DeviceType_CPU );
	InitDeviceByType( CL_DEVICE_TYPE_GPU, DeviceType_GPU );
}

void CLPlatform::InitDeviceByType( cl_device_type clType, DeviceType deviceType )
{
	cl_int status = CL_SUCCESS;
	cl_uint deviceCount = 0;

	status = clGetDeviceIDs( m_platformId, clType, 0, NULL, &deviceCount );
	if ( status == CL_SUCCESS )
	{
		cl_device_id* deviceIds = new cl_device_id[ deviceCount ];

		status = clGetDeviceIDs( m_platformId, clType, deviceCount, deviceIds, NULL );

		if ( status == CL_SUCCESS )
		{
			for ( uint32 i = 0; i < deviceCount; ++i )
			{
				DevicePtr device = new CLDevice( PlatformPtr( this ), deviceType, clType, deviceIds[ i ] );

				m_vecDevices.push_back( device );
			}

			cl_context_properties cps[ 3 ] = { CL_CONTEXT_PLATFORM, (cl_context_properties)m_platformId, 0 };
			cl_context context = clCreateContextFromType( cps, clType, NULL, NULL,	&status);

			if ( status == CL_SUCCESS )
			{
				m_mapDeviceCtx.insert( std::make_pair(deviceType, context ) );
			}
			else
			{
				// TODO: log clCreateContextFromType failed.
			}
		}
		else
		{
			// TODO: log
		}

		SAFE_DELETE_ARRAY( deviceIds );
	}
	else
	{
		//std::cout<<"Error: clGetDeviceIDs failed. Error code : ";
		//std::cout << streamsdk::getOpenCLErrorCodeStr(status) << std::endl;
	}

}

cl_platform_id CLPlatform::GetPlatformId() const
{
	return m_platformId;
}

